<!DOCTYPE html>
<html lang="en" >
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="author" content="GoJun" />
	
	
	
	<title>是时候让你项目用上 ViewBindings 了 ｜ GoJun</title>
	
    
    
    <meta name="description" content="写在前面 相信大多数人在写 findViewById 都是烦恼的，不少人会使用 ButterKnife 来简化，利用插件会自动生成绑定 View 代码，可是一旦界面控件多时候，就会出现几十行甚至上百行的 BindView 代码。此时有没有更好的框架来帮我们呢？ 答案是有的，在前不久" />
    

    
    
    <meta name="keywords" content="Hugo, theme, zozo" />
    

	
    
    <link rel="shortcut icon" href="https://gojun.me/images/favicon.ico" />

    <link rel="stylesheet" type="text/css" media="screen" href="https://gojun.mecss/normalize.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://cdn.jsdelivr.net/npm/animate.css@4.1.0/animate.min.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://gojun.me/css/zozo.css" />
	<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="https://gojun.me/css/highlight.css" />

    
    
</head>

<body>
    <div class="main animate__animated animate__fadeInDown">
        <div class="nav_container animated fadeInDown">
    <div class="site_nav" id="site_nav">
        <ul>
            
            <li>
                <a href="/">Home</a>
            </li>
            
            <li>
                <a href="/posts/">Archive</a>
            </li>
            
            <li>
                <a href="/tags/">Tags</a>
            </li>
            
            <li>
                <a href="/projects/">Projects</a>
            </li>
            
        </ul>
    </div>
    <div class="menu_icon">
        <a id="menu_icon"><i class="ri-menu-line"></i></a>
    </div>
</div>
        <div class="header animated fadeInDown">
    <div class="site_title_container">
        <div class="site_title">
            <h1>
                <a href="https://gojun.me">
                    <span>GoJun</span>
                </a>
            </h1>
        </div>
        <div class="description">
            <p class="sub_title">为向往生活努力奋斗！</p>
            <div class="my_socials">
                
                
                <a href="https://github.com/freelander" title="github" target="_blank"><i class="ri-github-fill"></i></a>
                
                
                <a href="https://gojun.me/index.xml" type="application/rss+xml" title="rss" target="_blank"><i
                        class="ri-rss-fill"></i></a>
            </div>
        </div>
    </div>
</div>
        <div class="content">
            <div class="post_page">
                <div class="post animate__animated animate__fadeInDown">
                    <div class="post_title post_detail_title">
                        <h2><a href='/posts/android-viewbindings/'>是时候让你项目用上 ViewBindings 了</a></h2>
                        <span class="date">2019.06.13</span>
                    </div>
                    <div class="post_content markdown"><h2 id="写在前面">写在前面</h2>
<p>相信大多数人在写 findViewById 都是烦恼的，不少人会使用 ButterKnife 来简化，利用插件会自动生成绑定 View 代码，可是一旦界面控件多时候，就会出现几十行甚至上百行的 BindView 代码。此时有没有更好的框架来帮我们呢？</p>
<p>答案是有的，在前不久的 Google IO 2019 上面提到了 ViewBindings 概念，后来我详细了解后，发现这个东西可以理解为 DataBinding 的一部分，具体区别在于 ViewBindings 只是视图绑定部分。想更深入了解两者区别，可以看下 <a href="https://proandroiddev.com/new-in-android-viewbindings-the-difference-from-databinding-library-bef5945baf5e">这篇文章</a></p>
<h2 id="使用">使用</h2>
<h3 id="构建-databingding-环境">构建 DataBingding 环境</h3>
<p>在 App 模块的 build.gradle 文件中添加 DataBinding 配置</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">android {
    ....
    dataBinding {
        enabled = true
    }
}
</code></pre></div><h3 id="在基类配置-bingding-代码">在基类配置 Bingding 代码</h3>
<h4 id="activity">Activity</h4>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">public class CustomActivity&lt;VB extends ViewDataBinding&gt; extends AppCompatActivity {

    private View mContentView;
    protected VB mViewBinding;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        mContentView = View.inflate(this, layoutResID, null);
        mViewBinding = DataBindingUtil.bind(mContentView);
        super.setContentView(mContentView);
    }
}
</code></pre></div><h4 id="fragment">Fragment</h4>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">public class CustomFragment&lt;VB extends ViewDataBinding&gt; extends BaseFragment {
    
    private View mContentView;
    protected VB mViewBinding;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return mContentView;
    }
    
    public void setContentView(int id) {
        this.mContentView = getActivity().getLayoutInflater().inflate(id, mContainer, false);
        mViewBinding = DataBindingUtil.bind(mContentView);
    }
}
</code></pre></div><h3 id="如何使用">如何使用</h3>
<h4 id="布局">布局</h4>
<p>在布局的最外层增加 <code>&lt;layout&gt;&lt;/layout&gt;</code> 标签</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&gt;
&lt;layout&gt;
    &lt;LinearLayout xmlns:android=&#34;http://schemas.android.com/apk/res/android&#34;
        xmlns:tools=&#34;http://schemas.android.com/tools&#34;
        android:layout_width=&#34;match_parent&#34;
        android:layout_height=&#34;match_parent&#34;
        android:background=&#34;@color/bg_grey_f2f2f2&#34;
        android:orientation=&#34;vertical&#34;&gt;

        &lt;com.chicdeals.widget.CustomRegularTextView
            android:id=&#34;@+id/tv_app_cache&#34;
            style=&#34;@style/CommonRippleStyle&#34;
            android:layout_width=&#34;match_parent&#34;
            android:layout_height=&#34;@dimen/space_50&#34;
            android:drawableEnd=&#34;@mipmap/ic_account_arrow_default&#34;
            android:drawablePadding=&#34;@dimen/space_12&#34;
            android:gravity=&#34;center_vertical&#34;
            android:paddingStart=&#34;@dimen/space_12&#34;
            android:paddingEnd=&#34;@dimen/space_12&#34;
            android:text=&#34;@string/account_change_password&#34;
            android:textColor=&#34;@color/text_grey_333333&#34;
            android:textSize=&#34;@dimen/textSize_15&#34; /&gt;

    &lt;/LinearLayout&gt;
&lt;/layout&gt;
</code></pre></div><h4 id="代码">代码</h4>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">public class SettingActivity extends CustomActivity&lt;SettingActivityBinding&gt; {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.setting_activity);
    }
    
    @Override
    public void initView() {
        super.initView();
        
        mViewBinding.tvAppCache.setText(getCacheSize());
    }
}
</code></pre></div><h3 id="视图点击事件">视图点击事件</h3>
<p>在引入 DataBinding 时，发现如果处理视图点击，还是需要逐一给视图设置点击事件的绑定，没有其他更好的方法，此时我选择了继续保留 ButterKnife 框架，可以快速绑定视图的点击事件</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">@OnClick({R.id.tv_change_pwd, R.id.tv_app_version, R.id.tv_app_cache, R.id.cv_sign_out})
public void onViewClicked(View view) {
    switch (view.getId()) {
        case R.id.tv_change_pwd:
            break;
        case R.id.tv_app_version:
            break;
        case R.id.tv_app_cache:
            break;
        case R.id.cv_sign_out:
            break;
    }
}
</code></pre></div><h2 id="结束">结束</h2>
<p>到这里简述大概如何使用 DataBinding 中的 ViewBinding 部分了。此时有人疑惑为什么不说说 DataBinding 数据绑定部分？</p>
<p>我简单说下几个原因：</p>
<ol>
<li>DataBinding 将部分逻辑移到布局文件，使得布局失去纯粹性，且逻辑变得有点乱，不利于阅读代码；</li>
<li>如果某个布局 xml 中的 DataBinding 代码有误，编译时会全部布局文件报错，不好定位报错地方；</li>
<li>在布局文件中插入了部分数据逻辑，使得文件失去了复用性。</li>
</ol>
<p>综上所述，我只建议大家使用 DataBinding 中的 View 绑定模块的 ViewBindings 框架，解决一个小小需求，替代 findViewById 使得项目代码更加简洁。</p>
</div>
                    <div class="post_footer">
                        
                        <div class="meta">
                            <div class="info">
                                <span class="field tags">
                                    <i class="ri-stack-line"></i>
                                    
                                    <a href="https://gojun.me/tags/android/">Android</a>
                                    
                                    <a href="https://gojun.me/tags/databinding/">DataBinding</a>
                                    
                                    <a href="https://gojun.me/tags/viewbindings/">ViewBindings</a>
                                    
                                </span>
                            </div>
                        </div>
                        
                    </div>
                </div>
                
                
                <div class="doc_comments"></div>
                
            </div>
        </div>
    </div>
    <a id="back_to_top" href="#" class="back_to_top"><i class="ri-arrow-up-s-line"></i></a>
    <footer class="footer">
    <div class="footer_slogan">
        <span></span>
    </div>
</footer>
    <script src="https://gojun.me/js/jquery-3.5.1.min.js"></script>
<link href="https://gojun.me/css/fancybox.min.css" rel="stylesheet">
<script src="https://gojun.me/js/fancybox.min.js"></script>
<script src="https://gojun.me/js/zozo.js"></script>


<script type="text/javascript" async
    src="https://cdn.bootcss.com/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
        MathJax.Hub.Config({
            tex2jax: {
                inlineMath: [['$', '$'], ['\\(', '\\)']],
                displayMath: [['$$', '$$'], ['\[\[', '\]\]']],
                processEscapes: true,
                processEnvironments: true,
                skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
                TeX: {
                    equationNumbers: { autoNumber: "AMS" },
                    extensions: ["AMSmath.js", "AMSsymbols.js"]
                }
            }
        });

        MathJax.Hub.Queue(function () {
            
            
            
            var all = MathJax.Hub.getAllJax(), i;
            for (i = 0; i < all.length; i += 1) {
                all[i].SourceElement().parentNode.className += ' has-jax';
            }
        });
    </script>

<style>
    code.has-jax {
        font: inherit;
        font-size: 100%;
        background: inherit;
        border: inherit;
        color: #515151;
    }
</style>



<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
	window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
	ga('create', 'UA-142037913-1', 'auto');
	
	ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>

</body>

</html>